﻿using KinonekoSoftware.CodariaDB.Documents.Timelines;

namespace KinonekoSoftware.CodariaDB.Core
{
    public sealed class TimeSystem  : Engine
    {
        
        #region Composition
        
        public void Add(Composition epoch)
        {
            if (epoch is null)
            {
                return;
            }
            
            CompositionDB.Insert(epoch);
            Modified();
        }
        public void Update(Composition epoch)
        {
            if (epoch is null)
            {
                return;
            }
            
            CompositionDB.Update(epoch);
            Modified();
        }

        public void Remove(Composition epoch)
        {
            if (epoch is null)
            {
                return;
            }
            
            CompositionDB.Delete(epoch.Id);
            Modified();
        }

        #endregion
        
        #region Epoch

        
        public void Add(Epoch epoch)
        {
            if (epoch is null)
            {
                return;
            }
            
            EpochDB.Insert(epoch);
            Modified();
        }
        
        
        
        public void Update(Epoch epoch)
        {
            if (epoch is null)
            {
                return;
            }
            
            EpochDB.Update(epoch);
            Modified();
        }
        
        public void Remove(Epoch epoch)
        {
            if (epoch is null)
            {
                return;
            }
            
            EpochDB.Delete(epoch.Id);
            Modified();
        }

        #endregion

        #region StoryPoint

        

        public StoryPoint GetDetached(string id) => DetachedStoryDB.FindById(id);

        public StoryPoint GetAttached(string id) => AttachedStoryDB.FindById(id);
        
        
        
        public void AddAttached(StoryPoint point)
        {
            if (point is null)
            {
                return;
            }

            AttachedStoryDB.Insert(point);
        }

        public void AddDetached(StoryPoint point)
        {
            if (point is null)
            {
                return;
            }
            
            DetachedStoryDB.Insert(point);
        }
        
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="point"></param>
        /// <remarks>注意：这个版本的更新方法会检查StoryPoint到底存在于哪个集合，平凡更新请使用对应的方法，如：<see cref="UpdateAttached"/>或者<see cref="UpdateDetached"/></remarks>
        public void Update(StoryPoint point)
        {
            if (point is null)
            {
                return;
            }

            if (DetachedStoryDB.HasID(point.Id))
            {
                UpdateDetached(point);
            }
            else
            {
                UpdateAttached(point);
            }
        }
        
        public void UpdateAttached(StoryPoint point)
        {
            if (point is null)
            {
                return;
            }

            AttachedStoryDB.Update(point);
        }

        public void UpdateDetached(StoryPoint point)
        {
            if (point is null)
            {
                return;
            }
            
            DetachedStoryDB.Update(point);
        }
        
        
        public void RemoveAttached(StoryPoint point)
        {
            if (point is null)
            {
                return;
            }

            AttachedStoryDB.Delete(point.Id);
            Modified();
        }

        public void RemoveDetached(StoryPoint point)
        {
            if (point is null)
            {
                return;
            }
            
            DetachedStoryDB.Delete(point.Id);
            Modified();
        }

        #endregion
        
        
        #region Plot
        
        public void Add(Plot epoch)
        {
            if (epoch is null)
            {
                return;
            }
            
            PlotDB.Insert(epoch);
            Modified();
        }
        public void Update(Plot epoch)
        {
            if (epoch is null)
            {
                return;
            }
            
            PlotDB.Update(epoch);
            Modified();
        }

        public void Remove(Plot epoch)
        {
            if (epoch is null)
            {
                return;
            }
            
            PlotDB.Delete(epoch.Id);
            Modified();
        }

        #endregion
        
        public IEnumerable<StoryPoint>  GetAttached()     => AttachedStoryDB.FindAll();
        public IEnumerable<StoryPoint>  GetDetached()     => DetachedStoryDB.FindAll();
        public IEnumerable<Epoch>       GetEpochs()       => EpochDB.FindAll();
        public IEnumerable<Composition> GetCompositions() => CompositionDB.FindAll();
        public IEnumerable<Plot>        GetPlots()        => PlotDB.FindAll();

        protected override void OnDatabaseOpening(RepositoryOpenContext context)
        {
            var repo = context.Repository;
            EpochDB         = repo.Get<Epoch>(CollectionNames.EpochDB);
            CompositionDB   = repo.Get<Composition>(CollectionNames.CompositionDB);
            DetachedStoryDB = repo.Get<StoryPoint>(CollectionNames.SubSystem_DetachedStoryDB);
            AttachedStoryDB = repo.Get<StoryPoint>(CollectionNames.SubSystem_AttchedStoryDB);
            StoryDB         = repo.Get<StoryRef>(CollectionNames.SubSystem_StoryDB);
            PlotDB          = repo.Get<Plot>(CollectionNames.SubSystem_PlotDB);
        }

        protected override void OnDatabaseClosing(ILogger logger)
        {
            EpochDB         = null;
            CompositionDB   = null;
            DetachedStoryDB = null;
            AttachedStoryDB = null;
            StoryDB         = null;
            PlotDB          = null;
        }

        public ILiteCollection<Epoch>       EpochDB         { get; private set; }
        public ILiteCollection<Plot>        PlotDB          { get; private set; }
        public ILiteCollection<Composition> CompositionDB   { get; private set; }
        public ILiteCollection<StoryPoint>  DetachedStoryDB { get; private set; }
        public ILiteCollection<StoryPoint>  AttachedStoryDB { get; private set; }
        public ILiteCollection<StoryRef>    StoryDB         { get; private set; }

        public override string EngineID => EngineNames.Timeline;

    }
}